﻿using DataService.Core.Extensions;
using DataService.Core.Log;
using DataService.Extensions;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace DataService.Common
{
    public abstract class DBSchemaSql
    {
        protected virtual string ParameterPrefix => "@";
        public virtual string GetInsertSql<T>(string fullTableName)
        {
            fullTableName= GetTableName(fullTableName);
            Type type = typeof(T);
            PropertyInfo[] fields = type.GetProperties();
            string data_Field = string.Join(",", fields.Select(s => s.Name));
            string para_Field_Value = string.Join(",", fields.Select(s => ParameterPrefix + s.Name));
            string sql = $"INSERT INTO {fullTableName}({data_Field}) VALUES({para_Field_Value})";
            TraceLog.WriteLine($"执行{sql}", "执行语句");
            return sql;
        }
        public virtual string GetUpdateSql<T>(List<string> pkFields, string fullTableName)
        {
            fullTableName = GetTableName(fullTableName);
            Type type = typeof(T);
            PropertyInfo[] fields = type.GetProperties();
            var setFiled_Value = fields.Where(f => !pkFields.Any(t => t == f.Name));//过滤主键
            string field_Value = string.Join(",", setFiled_Value.Select(s => s.Name + "=" + ParameterPrefix + s.Name));

            string pkparam = string.Join(" AND ", pkFields.Select(s => s + "=" + ParameterPrefix + s));

            string sql = $"UPDATE {fullTableName} SET {field_Value} WHERE {pkparam}";
            TraceLog.WriteLine($"执行{sql}", "执行语句");
            return sql;
        }
        public virtual string GetUpdateSql<T>(List<string> pkFields, Expression<Func<T, object>> fieldFunc, string fullTableName)
        {
            fullTableName = GetTableName(fullTableName);
            List<string> fielArray = FieldHelper.GetFieldArray(fieldFunc);
            var setFiled_Value = fielArray.Where(f => !pkFields.Any(t => t == f));//过滤主键
            string fields = string.Join(",", fielArray.Select(x => x + "=" + ParameterPrefix + x));
            string pkparam = string.Join(" AND ", pkFields.Select(s => s + "=" + ParameterPrefix + s));
            string sql = $"UPDATE {fullTableName} SET {fields} WHERE {pkparam}";
            TraceLog.WriteLine($"执行{sql}", "执行语句");
            return sql;
        }
        public virtual string GetDeleteSql<T>(Expression<Func<T, bool>> whereFunc, ref object paramValue, string fullTableName)
        {
            fullTableName = GetTableName(fullTableName);
            string sql = string.Empty;
            if (whereFunc == null)
            {
                throw new Exception("参数不能为null");
            }
            else
            {
                ResolveExpress resolve = new ResolveExpress();
                var dic = resolve.ResolveExpression<T>(whereFunc, ParameterPrefix);
                if (!dic.ContainsKey("sql"))
                {
                    throw new Exception("GetDeleteSql解析参数错误");
                }
                sql = $"DELETE FROM {fullTableName} WHERE {dic["sql"].ToString()}";
                paramValue = dic["values"];
            }
            TraceLog.WriteLine($"执行{sql}", "执行语句");
            return sql;
        }
        public virtual string GetSelectSql<T>(Expression<Func<T, bool>> whereFunc, ref object paramValue, string fullTableName, Expression<Func<T, object>> fieldFunc)
        {
            fullTableName = GetTableName(fullTableName);
            if (whereFunc == null)
            {
                PropertyInfo[] tempFields = typeof(T).GetProperties();
                string data_Field = string.Join(",", tempFields.Select(s => s.Name));
                string _sql = $"SELECT {data_Field} FROM {fullTableName}";
                return _sql;
            }
            ResolveExpress resolve = new ResolveExpress();
            var dic = resolve.ResolveExpression<T>(whereFunc, ParameterPrefix);
            if (!dic.ContainsKey("sql"))
            {
                throw new Exception("GetSelectSql解析参数错误");
            }
            string fields = "*";
            if (fieldFunc != null)
            {
                List<string> tempArray = FieldHelper.GetFieldArray(fieldFunc);
                fields = string.Join(",", tempArray);
            }

            string sql = $"SELECT {fields} FROM {fullTableName} WHERE {dic["sql"].ToString()}";
            paramValue = dic["values"];
            TraceLog.WriteLine($"执行{sql}", "执行语句");
            return sql;
        }
        public virtual string GetPageSelectSql<T>(Expression<Func<T, bool>> whereFunc, ref object paramValue, string fullTableName, Expression<Func<T, object>> fieldFunc)
        {
            //ResolveExpress resolve = new ResolveExpress();
            //var dic = resolve.ResolveExpression<T>(whereFunc);
            //if (!dic.ContainsKey("sql"))
            //{
            //    throw new Exception("GetSelectSql解析参数错误");
            //}
            fullTableName = GetTableName(fullTableName);
            string fields = "*";//先用 * 后面再优化
            if (fieldFunc != null)
            {
                var fields2 = FieldHelper.GetExpressMemberInfos(whereFunc);

                List<string> tempArray = FieldHelper.GetFieldArray(fieldFunc);

                tempArray.AddRange(fields2);
                tempArray = tempArray.Distinct().ToList();
                fields = string.Join(",", tempArray);

            }
            string sql = $"SELECT {fields} FROM {fullTableName}";

            return sql;
        }
        public virtual string GetSelectScalarCountSql<T>(Expression<Func<T, bool>> whereFunc, ref object paramValue, string fullTableName, string databaseName)
        {
            fullTableName = GetTableName(fullTableName);
            //超过百万数据时,count(1)会变吗，数据量越大count越慢,先这么查，优化阶段，从索引表查询数量
            ResolveExpress resolve = new ResolveExpress();
            var dic = resolve.ResolveExpression<T>(whereFunc, ParameterPrefix);
            if (!dic.ContainsKey("sql"))
            {
                throw new Exception("GetSelectSql解析参数错误");
            }
            string sql = $"SELECT Count(1) FROM {fullTableName} WHERE {dic["sql"].ToString()}";
            paramValue = dic["values"];
            TraceLog.WriteLine($"执行{sql}", "执行语句");
            return sql;
        }
        protected virtual string GetTableName(string fullName)
        {
            return fullName;
        }
    }
}
